package cn.dansj.service.Impl;

import cn.dansj.common.utils.transfer.ArrayUtils;
import cn.dansj.controller.InterfaceRequestController;
import cn.dansj.entity.RequestLog;
import cn.dansj.repository.RequestLogRepository;
import cn.dansj.service.RequestLogService;
import cn.dansj.common.utils.transfer.Verification;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import jakarta.persistence.criteria.Predicate;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class RequestLogServiceImpl implements RequestLogService {
    private final RequestLogRepository requestLogRepository;
    private final List<String> defaultRejectController = ArrayUtils.asList(InterfaceRequestController.class.getName(), "dataController.runSql");

    public RequestLogServiceImpl(RequestLogRepository requestLogRepository) {
        this.requestLogRepository = requestLogRepository;
    }

    @Override
    public void save(List<RequestLog> requestLogs) {
        requestLogRepository.saveAll(requestLogs);
    }

    @Override
    public void save(RequestLog requestLog) {
        requestLogRepository.save(requestLog);
    }

    @Override
    public Page<RequestLog> search(Integer pageNum, Integer pageLimit, String url, int status, long cost, String date, String controller, String loginUser, int apiType) {
        return search(pageNum, pageLimit, Verification.checkNotNull(url) ? Collections.singletonList(url) : null, status, cost, date, controller, loginUser, apiType);
    }

    @Override
    public Page<RequestLog> search(Integer pageNum, Integer pageLimit, List<String> url, int status, long cost, String date, String controller, String loginUser, int apiType) {
        Sort sort = Sort.by(Sort.Direction.DESC, "crtTime");
        Pageable pageable = PageRequest.of(pageNum - 1, pageLimit, sort);
        Specification<RequestLog> specification = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> paramsList = new ArrayList<>();
            List<Predicate> urlPredicates = new ArrayList<>();

            if (Verification.checkNotNull(url)) {
                for (String u : url) {
                    urlPredicates.add(criteriaBuilder.equal(root.get("url"), u));
                }
                paramsList.add(criteriaBuilder.or(urlPredicates.toArray(new Predicate[]{})));
            }

            if (Verification.checkNotNull(loginUser)) {
                paramsList.add(criteriaBuilder.equal(root.get("loginUser"), loginUser));
            }

            if (status >= 0) {
                paramsList.add(criteriaBuilder.equal(root.get("status"), status));
            }

            if (cost > 0) {
                paramsList.add(criteriaBuilder.greaterThanOrEqualTo(root.get("cost"), cost));
            }

            if (apiType >= 0) {
                paramsList.add(criteriaBuilder.equal(root.get("apiType"), apiType));
            }

            if (Verification.checkNull(controller)) {
                paramsList.add(criteriaBuilder.or(criteriaBuilder.not(root.get("controller").in(defaultRejectController)), criteriaBuilder.isNull(root.get("controller"))));
            } else {
                paramsList.add(criteriaBuilder.equal(root.get("controller"), controller));
            }

            if (Verification.checkNotNull(date)) {
                String[] timeSplit = date.split(",");
                String startTime = timeSplit[0];
                String endTime;
                if (timeSplit.length == 2) {
                    endTime = timeSplit[1];
                } else {
                    endTime = startTime;
                }

                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    Date sTime = simpleDateFormat.parse(startTime);
                    Date eTime = simpleDateFormat.parse(endTime);
                    Calendar instance = Calendar.getInstance();
                    instance.setTime(eTime);
                    instance.add(Calendar.DATE, 1);
                    Predicate ge = criteriaBuilder.greaterThanOrEqualTo(root.get("crtTime"), sTime);
                    Predicate lt = criteriaBuilder.lessThan(root.get("crtTime"), instance.getTime());
                    paramsList.add(criteriaBuilder.and(ge, lt));

                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }

            Predicate[] predicates = new Predicate[paramsList.size()];
            return criteriaBuilder.and(paramsList.toArray(predicates));
        };
        return requestLogRepository.findAll(specification, pageable);
    }
}
